#pragma once

#include "TcpServer.hpp"
#include "Socket.hpp"
#include "InetAddr.hpp"
#include "Util.hpp"
#include "Log.hpp"
#include <string>
#include <memory>
#include <unordered_map>
#include <sstream>

using namespace LogModule;

const std::string gspace = " ";        // 空格符
const std::string glinespace = "\r\n"; // 换行符
const std::string gsep2 = ": ";        // 相应报头key: value分隔符

const std::string webroot = "./wwwroot";   // 网站根目录
const std::string homepage = "index.html"; // 默认首页

// http请求类
class HttpRequest
{
public:
    // 构造函数
    HttpRequest() {}

    // 序列化函数
    std::string Serialize()
    {
        return std::string();
    }

    // 对请求行进行反序列化函数
    void ParseReqLine(std::string reqline)
    {
        std::stringstream ss(reqline);
        ss >> _method >> _uri >> _version;
    }

    // 反序列化函数
    bool DeSerialize(std::string &reqstr)
    {
        // 1. 提取请求行
        std::string reqline;                                      // 请求行
        bool n = Util::ReadOneLine(reqstr, &reqline, glinespace); // 提取请求行并擦除
        LOG(LogLevel::DEBUG) << "请求行: " << reqline;

        // 2. 对请求行进行反序列化
        ParseReqLine(reqline);

        if (_uri == "/") // 默认首页
        {
            // /
            // ./wwwroot/index.html
            _uri = webroot + "/" + homepage;
        }
        else
        {
            // a/b/c.html
            // ./wwwroot/a/b/c.html
            _uri = webroot + _uri;
        }

        return true;
    }

    // 获取_uri
    std::string Get_uri() const { return _uri; }

    // 析构函数
    ~HttpRequest() {}

private:
    std::string _method;  // 请求方法
    std::string _uri;     // uri
    std::string _version; // 版本

    std::unordered_map<std::string, std::string> _headers; // 请求报头
    std::string _blankline;                                // 空行
    std::string _text;                                     // 请求正文
};

// http响应类 response
class HttpResponse
{
public:
    // 构造函数
    HttpResponse() : _blankline(glinespace)
    {
    }

    // 序列化函数
    std::string Serialize()
    {
        // 拼接状态行
        std::string status_line = _version + gspace + _code + gspace + _desc + glinespace;
        // 拼接响应报头
        std::string resp_header;
        for (auto &header : _headers)
        {
            std::string line = header.first + gsep2 + header.second + glinespace;
            resp_header += line;
        }
        // 拼接响应正文
        return status_line + resp_header + _blankline + _text;
    }

    // 反序列化函数
    bool DeSerialize(const std::string &reqstr)
    {
        return true;
    }

    // 填充正文_text, 将_targetfile文件内容读入_text
    bool MakeResponse()
    {
        bool ret = Util::ReadFileContent(_targetfile, &_text);
        if(!ret)
        {
            // 未查找到目标文件
            _code = "404";
            _desc = "Not Found";
        }
    }

    // 设置_targetfile函数
    void SetTargetFile(const std::string &target) { _targetfile = target; }

    // 析构函数
    ~HttpResponse() {}

public:
    // private:
    std::string _version; // 版本
    std::string _code;    // 状态码
    std::string _desc;    // 状态描述

    std::unordered_map<std::string, std::string> _headers; // 响应报头
    std::string _blankline;                                // 空行
    std::string _text;                                     // 响应正文

    std::string _targetfile; // 目标文件
};

// http类
class Http
{
public:
    // 构造函数
    Http(uint16_t port) : _tsvrp(std::make_unique<TcpServer>(port))
    {
    }

    // 处理客户端请求http格式函数, 处理Request, 返回Response
    void HanlderHttpRequest(std::shared_ptr<Socket> &sock, InetAddr &client)
    {
        // 接收请求, httpreqstr接收序列化字符串
        std::string httpreqstr;
        int n = sock->Recv(&httpreqstr);

        // todo 解码

        // 反序列化, req接收反序列化对象
        if (n > 0)
        {
            // 接收成功
            HttpRequest req;
            req.DeSerialize(httpreqstr);          // 反序列化, 填充HttpRequest成员属性 _method >> _url >> _version;
            std::string filename = req.Get_uri(); // 获取uri

            // 构建返回应答resp
            HttpResponse resp;
            resp.SetTargetFile(filename); // 设置目标文件
            resp.MakeResponse();          // 填充正文_text, 将_targetfile文件内容读入_text

            /* // 设置各成员变量
            resp._version = "HTTP/1.1";
            resp._code = "200";
            resp._desc = "OK";
            bool ret = Util::ReadFileContent(filename, &(resp._text)); // 拷贝填充文件内容
            LOG(LogLevel::DEBUG) << "ret: " << ret << ", 用户请求文件: " << filename;
            std::cout << std::endl; */

            // resp序列化
            std::string response_str = resp.Serialize();

            // 发送response_str
            sock->Send(response_str);
        }
        /* else { // 接收失败 } */

#ifdef DEBUG
        // #define DEBUG
        //  接收请求req
        std::string httpreqstr;
        sock->Recv(&httpreqstr);
        std::cout << httpreqstr;

        // 构建返回应答resp
        HttpResponse resp;
        // 设置各成员变量
        resp._version = "HTTP/1.1";
        resp._code = "200";
        resp._desc = "OK";
        // resp._headers
        std::string filename = webroot + homepage;               // 默认首页
        bool ret = Util::ReadFileContent(filename, &resp._text); // 拷贝填充文件内容

        //  resp序列化 -> response_str
        std::string response_str = resp.Serialize();

        // 发送response_str
        sock->Send(response_str);

#endif
    }

    // 启动函数
    void Start()
    {

        _tsvrp->Start([this](std::shared_ptr<Socket> &sock, InetAddr &client)
                      { this->HanlderHttpRequest(sock, client); });
    }

    // 析构函数
    ~Http()
    {
    }

private:
    std::unique_ptr<TcpServer> _tsvrp; // TcpServer智能指针
};
